From 13e64fdddd1ed5d14fbb20f69f642369faf8694e Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Thu, 24 Aug 2017 20:39:03 +0200 Subject: [PATCH] babl: iterate on public space/icc API --- babl/babl-icc.c | 113 ++++----------------------------------- babl/babl-internal.h | 3 +- babl/babl-space.c | 56 +++++++++---------- babl/babl-trc.c | 90 +++++++++++++++++++++++++++++++ babl/babl.h | 89 ++++++++++++++++++++---------- tools/babl-icc-rewrite.c | 16 +++--- 6 files changed, 198 insertions(+), 169 deletions(-) diff --git a/babl/babl-icc.c b/babl/babl-icc.c index 8f00851..41cee50 100644 --- a/babl/babl-icc.c +++ b/babl/babl-icc.c @@ -299,97 +299,6 @@ static int icc_tag (ICC *state, return 0; } -static const Babl *babl_trc_lut_find (float *lut, int lut_size) -{ - int i; - int match = 1; - - /* look for linear match */ - for (i = 0; match && i < lut_size; i++) - if (fabs (lut[i] - i / (lut_size-1.0)) > 0.015) - match = 0; - if (match) - return babl_trc_gamma (1.0); - - /* look for 2.2 match: */ - match = 1; - if (lut_size > 1024) - { - for (i = 0; match && i < lut_size; i++) - { -#if 0 - fprintf (stderr, "%i %f %f\n", i, - lut[i], - pow ((i / (lut_size-1.0)), 2.2)); -#endif - if (fabs (lut[i] - pow ((i / (lut_size-1.0)), 2.2)) > 0.0001) - match = 0; - } - } - else - { - for (i = 0; match && i < lut_size; i++) - { - if (fabs (lut[i] - pow ((i / (lut_size-1.0)), 2.2)) > 0.001) - match = 0; - } - } - if (match) - return babl_trc_gamma(2.2); - - - /* look for 1.8 match: */ - match = 1; - if (lut_size > 1024) - { - for (i = 0; match && i < lut_size; i++) - { -#if 0 - fprintf (stderr, "%i %f %f\n", i, - lut[i], - pow ((i / (lut_size-1.0)), 1.8)); -#endif - if (fabs (lut[i] - pow ((i / (lut_size-1.0)), 1.8)) > 0.0001) - match = 0; - } - } - else - { - for (i = 0; match && i < lut_size; i++) - { - if (fabs (lut[i] - pow ((i / (lut_size-1.0)), 1.8)) > 0.001) - match = 0; - } - } - if (match) - return babl_trc_gamma(2.2); - - - /* look for sRGB match: */ - match = 1; - if (lut_size > 1024) - { - for (i = 0; match && i < lut_size; i++) - { - if (fabs (lut[i] - gamma_2_2_to_linear (i / (lut_size-1.0))) > 0.0001) - match = 0; - } - } - else - { - for (i = 0; match && i < lut_size; i++) - { - if (fabs (lut[i] - gamma_2_2_to_linear (i / (lut_size-1.0))) > 0.001) - match = 0; - } - } - if (match) - return babl_trc ("sRGB"); - - - return NULL; -} - static const Babl *babl_trc_from_icc (ICC *state, int offset, char **error) { @@ -465,10 +374,9 @@ switch (trc->type) icc_write (u32, state->o + 8, 1); icc_write (u8f8, state->o + 12, trc->gamma); break; - case BABL_TRC_SRGB: { - int lut_size = 1024; + int lut_size = 512; icc_allocate_tag (state, name, 13 + lut_size * 2); icc_write (sign, state->o, "curv"); icc_write (u32, state->o + 4, 0); @@ -476,12 +384,11 @@ switch (trc->type) { int j; for (j = 0; j < lut_size; j ++) - icc_write (u16, state->o + 12 + j * 2, + icc_write (u16, state->o + 12 + j * 2, gamma_2_2_to_linear (j / (lut_size-1.0)) * 65535.5); } } break; - case BABL_TRC_LUT: icc_allocate_tag (state, name, 13 + trc->lut_size * 2); icc_write (sign, state->o, "curv"); @@ -505,7 +412,7 @@ switch (trc->type) static void symmetry_test (ICC *state); -const char *babl_space_rgb_to_icc (const Babl *babl, int *ret_length) +const char *babl_space_to_icc (const Babl *babl, int *ret_length) { const BablSpace *space = &babl->space; static char icc[65536]; @@ -627,11 +534,11 @@ const char *babl_space_rgb_to_icc (const Babl *babl, int *ret_length) } const Babl * -babl_space_rgb_icc (const char *icc, - int length, - char **error) +babl_space_from_icc (const char *icc_data, + int icc_length, + char **error) { - ICC *state = icc_state_new ((char*)icc, length, 0); + ICC *state = icc_state_new ((char*)icc_data, icc_length, 0); int profile_size = icc_read (u32, 0); int icc_ver_major = icc_read (u8, 8); @@ -640,7 +547,7 @@ babl_space_rgb_icc (const char *icc, const Babl *trc_blue = NULL; sign_t profile_class, color_space; - if (profile_size != length) + if (profile_size != icc_length) { *error = "icc profile length inconsistency"; } @@ -719,7 +626,7 @@ babl_space_rgb_icc (const char *icc, babl_free (state); - return babl_space_rgb_matrix (NULL, + return babl_space_from_rgbxyz_matrix (NULL, wX, wY, wZ, rx, gx, bx, ry, gy, by, @@ -762,7 +669,7 @@ babl_space_rgb_icc (const char *icc, double wZ = icc_read (s15f16, offset + 8 + 4 * 2); babl_free (state); - return babl_space_rgb_chromaticities (NULL, + return babl_space_from_chromaticities (NULL, wX / (wX + wY + wZ), wY / (wX + wY + wZ), red_x, red_y, diff --git a/babl/babl-internal.h b/babl/babl-internal.h index 4232710..9ba8a85 100644 --- a/babl/babl-internal.h +++ b/babl/babl-internal.h @@ -398,7 +398,8 @@ void babl_space_from_xyz (const Babl *space, const double *xyz, double *rgb); const Babl *babl_space_from_icc (const char *icc, int length, char **error); +const Babl *babl_trc_lut_find (float *lut, int lut_size); +const Babl * babl_trc_lut (const char *name, int n, float *entries); -const char *babl_space_rgb_to_icc (const Babl *space, int *ret_length); #endif diff --git a/babl/babl-space.c b/babl/babl-space.c index 4fbd310..cd7c4e2 100644 --- a/babl/babl-space.c +++ b/babl/babl-space.c @@ -144,14 +144,14 @@ babl_space (const char *name) } const Babl * -babl_space_rgb_matrix (const char *name, - double wx, double wy, double wz, - double rx, double gx, double bx, - double ry, double gy, double by, - double rz, double gz, double bz, - const Babl *trc_red, - const Babl *trc_green, - const Babl *trc_blue) +babl_space_from_rgbxyz_matrix (const char *name, + double wx, double wy, double wz, + double rx, double gx, double bx, + double ry, double gy, double by, + double rz, double gz, double bz, + const Babl *trc_red, + const Babl *trc_green, + const Babl *trc_blue) { int i=0; static BablSpace space; @@ -222,14 +222,14 @@ babl_space_rgb_matrix (const char *name, const Babl * -babl_space_rgb_chromaticities (const char *name, - double wx, double wy, - double rx, double ry, - double gx, double gy, - double bx, double by, - const Babl *trc_red, - const Babl *trc_green, - const Babl *trc_blue) +babl_space_from_chromaticities (const char *name, + double wx, double wy, + double rx, double ry, + double gx, double gy, + double bx, double by, + const Babl *trc_red, + const Babl *trc_green, + const Babl *trc_blue) { int i=0; static BablSpace space; @@ -295,14 +295,14 @@ babl_space_class_for_each (BablEachFunction each_fun, void babl_space_class_init (void) { - babl_space_rgb_chromaticities ("sRGB", + babl_space_from_chromaticities ("sRGB", 0.3127, 0.3290, /* D65 */ 0.6400, 0.3300, 0.3000, 0.6000, 0.1500, 0.0600, babl_trc("sRGB"), NULL, NULL); - babl_space_rgb_chromaticities ( + babl_space_from_chromaticities ( "Adobe", 0.3127, 0.3290, /* D65 */ 0.6400, 0.3300, @@ -310,7 +310,7 @@ babl_space_class_init (void) 0.1500, 0.0600, babl_trc("2.2"), NULL, NULL); - babl_space_rgb_chromaticities ( + babl_space_from_chromaticities ( "ProPhoto", 0.34567, 0.3585, /* D50 */ 0.7347, 0.2653, @@ -318,7 +318,7 @@ babl_space_class_init (void) 0.0366, 0.0001, babl_trc("1.8"), NULL, NULL); - babl_space_rgb_chromaticities ( + babl_space_from_chromaticities ( "Apple", 0.3127, 0.3290, /* D65 */ 0.6250, 0.3400, @@ -326,7 +326,7 @@ babl_space_class_init (void) 0.1550, 0.0700, babl_trc("1.8"), NULL, NULL); - babl_space_rgb_chromaticities ( + babl_space_from_chromaticities ( "Best", 0.34567, 0.3585, /* D50 */ 0.7347, 0.2653, @@ -334,7 +334,7 @@ babl_space_class_init (void) 0.1300, 0.0350, babl_trc("2.2"), NULL, NULL); - babl_space_rgb_chromaticities ( + babl_space_from_chromaticities ( "Beta", 0.34567, 0.3585, /* D50 */ 0.6888, 0.3112, @@ -342,7 +342,7 @@ babl_space_class_init (void) 0.1265, 0.0352, babl_trc("2.2"), NULL, NULL); - babl_space_rgb_chromaticities ( + babl_space_from_chromaticities ( "Bruce", 0.3127, 0.3290, /* D65 */ 0.6400, 0.3300, @@ -350,7 +350,7 @@ babl_space_class_init (void) 0.1500, 0.0600, babl_trc("1.8"), NULL, NULL); - babl_space_rgb_chromaticities ( + babl_space_from_chromaticities ( "PAL", 0.3127, 0.3290, /* D65 */ 0.6400, 0.3300, @@ -358,7 +358,7 @@ babl_space_class_init (void) 0.1500, 0.0600, babl_trc("2.2"), NULL, NULL); - babl_space_rgb_chromaticities ( + babl_space_from_chromaticities ( "SMPTE-C", 0.3127, 0.3290, /* D65 */ 0.6300, 0.3300, @@ -366,7 +366,7 @@ babl_space_class_init (void) 0.1550, 0.0700, babl_trc("2.2"), NULL, NULL); - babl_space_rgb_chromaticities ( + babl_space_from_chromaticities ( "ColorMatch", 0.34567, 0.3585, /* D50 */ 0.6300, 0.3400, @@ -374,7 +374,7 @@ babl_space_class_init (void) 0.1500, 0.0750, babl_trc("1.8"), NULL, NULL); - babl_space_rgb_chromaticities ( + babl_space_from_chromaticities ( "Don RGB 4", 0.34567, 0.3585, /* D50 */ 0.6960, 0.3000, @@ -382,7 +382,7 @@ babl_space_class_init (void) 0.1300, 0.0350, babl_trc("1.8"), NULL, NULL); - babl_space_rgb_chromaticities ( + babl_space_from_chromaticities ( "WideGamutRGB", 0.34567, 0.3585, /* D50 */ 0.7350, 0.2650, diff --git a/babl/babl-trc.c b/babl/babl-trc.c index 49ff6fd..f63a984 100644 --- a/babl/babl-trc.c +++ b/babl/babl-trc.c @@ -164,3 +164,93 @@ float babl_trc_to_linearf (const Babl *trc_, float value) return _babl_trc_to_linearf (trc_, value); } +const Babl *babl_trc_lut_find (float *lut, int lut_size) +{ + int i; + int match = 1; + + /* look for linear match */ + for (i = 0; match && i < lut_size; i++) + if (fabs (lut[i] - i / (lut_size-1.0)) > 0.015) + match = 0; + if (match) + return babl_trc_gamma (1.0); + + /* look for 2.2 match: */ + match = 1; + if (lut_size > 1024) + { + for (i = 0; match && i < lut_size; i++) + { +#if 0 + fprintf (stderr, "%i %f %f\n", i, + lut[i], + pow ((i / (lut_size-1.0)), 2.2)); +#endif + if (fabs (lut[i] - pow ((i / (lut_size-1.0)), 2.2)) > 0.0001) + match = 0; + } + } + else + { + for (i = 0; match && i < lut_size; i++) + { + if (fabs (lut[i] - pow ((i / (lut_size-1.0)), 2.2)) > 0.001) + match = 0; + } + } + if (match) + return babl_trc_gamma(2.2); + + + /* look for 1.8 match: */ + match = 1; + if (lut_size > 1024) + { + for (i = 0; match && i < lut_size; i++) + { +#if 0 + fprintf (stderr, "%i %f %f\n", i, + lut[i], + pow ((i / (lut_size-1.0)), 1.8)); +#endif + if (fabs (lut[i] - pow ((i / (lut_size-1.0)), 1.8)) > 0.0001) + match = 0; + } + } + else + { + for (i = 0; match && i < lut_size; i++) + { + if (fabs (lut[i] - pow ((i / (lut_size-1.0)), 1.8)) > 0.001) + match = 0; + } + } + if (match) + return babl_trc_gamma(2.2); + + + /* look for sRGB match: */ + match = 1; + if (lut_size > 1024) + { + for (i = 0; match && i < lut_size; i++) + { + if (fabs (lut[i] - gamma_2_2_to_linear (i / (lut_size-1.0))) > 0.0001) + match = 0; + } + } + else + { + for (i = 0; match && i < lut_size; i++) + { + if (fabs (lut[i] - gamma_2_2_to_linear (i / (lut_size-1.0))) > 0.001) + match = 0; + } + } + if (match) + return babl_trc ("sRGB"); + + return NULL; +} + diff --git a/babl/babl.h b/babl/babl.h index e05ea49..a992dad 100644 --- a/babl/babl.h +++ b/babl/babl.h @@ -96,7 +96,6 @@ const Babl * babl_trc (const char *name); */ const Babl * babl_trc_gamma (double gamma); -const Babl * babl_trc_lut (const char *name, int n, float *entries); /** @@ -109,54 +108,86 @@ const Babl * babl_trc_lut (const char *name, int n, float *entries); const Babl * babl_space (const char *name); /** - * babl_space_rgb_chromaticities: + * babl_space_from_chromaticities: * - * Creates a new RGB matrix color space definition with the specified - * white point wx, wy, primary chromaticities rx,ry,gx,gy,bx,by and - * TRCs to be used. After registering a new babl-space it can be used - * with babl_space() passing its name; + * Creates a new babl-space/ RGB matrix color space definition with the + * specified CIE xy(Y) values for white point: wx, wy and primary + * chromaticities: rx,ry,gx,gy,bx,by and TRCs to be used. After registering a + * new babl-space it can be used with babl_space() passing its name; + * + * Internally this does the math to derive the RGBXYZ matrix as used in an ICC + * profile. */ -const Babl * babl_space_rgb_chromaticities (const char *name, - double wx, double wy, - double rx, double ry, - double gx, double gy, - double bx, double by, - const Babl *trc_red, - const Babl *trc_green, - const Babl *trc_blue); +const Babl * babl_space_from_chromaticities (const char *name, + double wx, double wy, + double rx, double ry, + double gx, double gy, + double bx, double by, + const Babl *trc_red, + const Babl *trc_green, + const Babl *trc_blue); /** - * babl_space_rgb_matrix: + * babl_space_from_rgbxyz_matrix: * - * Creates a new RGB matrix color space definition using a precomputed - * D50 adapted 3x3 matrix, as possibly read from an ICC profile. + * Creates a new RGB matrix color space definition using a precomputed D50 + * adapted 3x3 matrix and associated CIE XYZ whitepoint, as possibly read from + * an ICC profile. */ const Babl * -babl_space_rgb_matrix (const char *name, - double wx, double wy, double wz, - double rx, double gx, double bx, - double ry, double gy, double by, - double rz, double gz, double bz, - const Babl *trc_red, - const Babl *trc_green, - const Babl *trc_blue); +babl_space_from_rgbxyz_matrix (const char *name, + double wx, double wy, double wz, + double rx, double gx, double bx, + double ry, double gy, double by, + double rz, double gz, double bz, + const Babl *trc_red, + const Babl *trc_green, + const Babl *trc_blue); /** - * babl_space_rgb_icc: + * babl_space_from_icc: * * Create a babl space from an in memory ICC profile, the * profile does no longer need to be loaded for the space to work, * multiple calls with the same icc profile will result in the * same space. * + * For now, limited to v2 ICC profiles, support for v4 profiles will be added. + * + * babl uses internal parametric TRCs when the provided LUTs are sufficiently + * similar. + * * If a BablSpace cannot be created from the profile NULL is returned and * a static string is set on the provided error location. */ -const Babl *babl_space_rgb_icc (const char *icc, - int length, - char **error); +const Babl *babl_space_from_icc (const char *icc_data, + int icc_length, + char **error); + + +/* babl_space_to_icc: + * + * Creates an ICCv2 RGB matrix profile for a babl space. The profiles strive to + * be as small and compact as possible, TRCs are stored as 1024 entry LUT(s). + */ +const char *babl_space_to_icc (const Babl *space, int *icc_length); + +/* babl_space_get_rgbtoxyz: + Returns the internal, double-precision 3x3 matrix used to convert linear + RGB data to CIE XYZ. + */ const double * babl_space_get_rgbtoxyz (const Babl *space); + +/* babl_space_to_xyz: + * + * converts a double triplet from linear RGB to CIE XYZ. + */ void babl_space_to_xyz (const Babl *space, const double *rgb, double *xyz); + +/* babl_space_from_xyz: + * + * converts double triplet from CIE XYZ to linear RGB + */ void babl_space_from_xyz (const Babl *space, const double *xyz, double *rgb); /** diff --git a/tools/babl-icc-rewrite.c b/tools/babl-icc-rewrite.c index 4cce694..bf18bc7 100644 --- a/tools/babl-icc-rewrite.c +++ b/tools/babl-icc-rewrite.c @@ -32,8 +32,8 @@ main (int argc, char **argv) { const Babl *babl; - char *icc = NULL; - long len; + char *icc_data = NULL; + long icc_len; int genlen; char *error = NULL; babl_init (); @@ -44,16 +44,16 @@ main (int argc, return -1; } - if (file_get_contents (argv[1], &icc, &len, NULL)) + if (file_get_contents (argv[1], &icc_data, &icc_len, NULL)) return -1; - babl = babl_space_rgb_icc (icc, len, &error); - free (icc); + babl = babl_space_from_icc (icc_data, icc_len, &error); + free (icc_data); - icc = (char *)babl_space_rgb_to_icc (babl, &genlen); - if (icc) + icc_data = (char *)babl_space_to_icc (babl, &genlen); + if (icc_data) { - file_set_contents (argv[2], icc, genlen); + file_set_contents (argv[2], icc_data, genlen); } babl_exit (); -- 2.30.2